package uk.co.hs.web.controller.admin;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;

import uk.co.hs.constants.AdminGeneralConstants;
import uk.co.hs.domain.web.WebRole;
import uk.co.hs.domain.web.WebRoleUrl;
import uk.co.hs.domain.web.WebUrl;
import uk.co.hs.domain.web.WebUser;
import uk.co.hs.service.admin.interfaces.WebRoleServiceInterface;
import uk.co.hs.service.admin.interfaces.WebUserServiceInterface;
import uk.co.hs.web.command.admin.RoleCommand;
import uk.co.hs.web.interceptor.TabsAccessibilityInterceptor;
import uk.co.hs.web.util.RoleUrlWeb;

/**
 * RoleEditController.
 */
@Controller("hs_roleEditController")
@RequestMapping("/" + TabsAccessibilityInterceptor.ROLE_EDIT_URL)
@SessionAttributes(AdminGeneralConstants.ADMIN_COMMAND)
public class RoleEditController extends AdminEditController
{
  @Resource
  private WebRoleServiceInterface mRoleService;

  @Resource
  private WebUserServiceInterface mUserService;

  /**
   * Form Backing Object.
   *
   * @param aRequest HttpServletRequest.
   * @return ModelAndView.
   */
  @RequestMapping(method = RequestMethod.GET)
  protected ModelAndView formBackingObject(HttpServletRequest aRequest)
  {
    RoleCommand command = new RoleCommand();

    // Get logged on user's role
    String loggedOnUserName = SecurityContextHolder.getContext().getAuthentication().getName();
    if (loggedOnUserName != null)
    {
      WebUser loggedOnUser = mUserService.getWebUser(loggedOnUserName);
      if (loggedOnUser != null)
      {
      	command.setLoggedOnUserName(loggedOnUserName);

      	WebRole loggedOnUserRole = loggedOnUser.getRole();
        if (loggedOnUserRole != null)
        {
          command.setLoggedOnRoleName(loggedOnUserRole.getName());
        }
      }
    }

    List<WebUrl> listUrl = mRoleService.getAllWebUrls();
    List<RoleUrlWeb> listRoleUrlWeb = new ArrayList<RoleUrlWeb>();
    List<String> linkedUsernames = new ArrayList<String>();
    RoleUrlWeb currentNewRoleUrlWeb;

    String idParam = aRequest.getParameter("id_0");
    if (idParam == null || idParam.isEmpty()) // New Role
    {
      command.setIsNew(true);
      for (WebUrl url : listUrl)
      {
        currentNewRoleUrlWeb = new RoleUrlWeb(url);
        currentNewRoleUrlWeb.setAccess(url.getAllowByDefault());
        currentNewRoleUrlWeb.setEditable(url.getWriteByDefault());
        listRoleUrlWeb.add(currentNewRoleUrlWeb);
      }
    }
    else // Existing Role
    {
      Long rolePk = new Long(aRequest.getParameter("id_0"));
      command.setIsNew(false);

      WebRole role = mRoleService.getWebRole(rolePk);
      command.setRole(role);

      List<WebRoleUrl> listRoleUrl = mRoleService.getWebRoleUrls(role.getPk());
      for (WebUrl url : listUrl)
      {
        currentNewRoleUrlWeb = new RoleUrlWeb(url);
        currentNewRoleUrlWeb.setAccess(false);
        currentNewRoleUrlWeb.setEditable(false);

        for (WebRoleUrl roleUrl : listRoleUrl)
        {
          if (url.getUrl().equals(roleUrl.getUrl().getUrl()))
          {
            currentNewRoleUrlWeb.setAccess(true);
            currentNewRoleUrlWeb.setEditable(roleUrl.getEditable());
            currentNewRoleUrlWeb.setRole(roleUrl.getRole());
            break;
          }
        }
        listRoleUrlWeb.add(currentNewRoleUrlWeb);
      }

      List<WebUser> users = role.getUsers();
      for (WebUser currentUser : users)
      {
        if (currentUser.getEndDate() == null)
        {
          linkedUsernames.add(currentUser.getUsername());
        }
      }
    }

    command.setListOfRoleUrlWebs(listRoleUrlWeb);
    command.setLinkedUserNames(linkedUsernames);

    ModelAndView mav = new ModelAndView(getViewName());
    mav.addObject(AdminGeneralConstants.ADMIN_COMMAND, command);
    return mav;
  }

  /**
   * Save detail.
   *
   * @param aRequest HttpServletRequest.
   * @param aCommand RoleCommand.
   * @param aErrors Errors.
   * @return ModelAndView.
   */
  @RequestMapping(params = "adminRequestedAction" + "=save", method = RequestMethod.POST)
  public ModelAndView saveDetail(HttpServletRequest aRequest,
                                 @ModelAttribute(AdminGeneralConstants.ADMIN_COMMAND) RoleCommand aCommand,
                                 Errors aErrors)
  {
    String errorMessage = mRoleService.saveWebRoleAndWebUrlLinks(aCommand.getRole(), aCommand.getListOfRoleUrlWebs());
    if (errorMessage != null)
    {
      aErrors.reject(errorMessage, new String[] {"Role"}, "Role");

      ModelAndView mav = new ModelAndView(getViewName());
      mav.addObject(AdminGeneralConstants.ADMIN_COMMAND, aCommand);
      return mav;
    }
    return getRedirectListView();
  }

  /**
   * Cancel.
   *
   * @return ModelAndView.
   */
  @RequestMapping(params = "adminRequestedAction" + "=cancel", method = RequestMethod.POST)
  public ModelAndView cancel()
  {
    return getRedirectListView();
  }

  /**
   * Delete.
   *
   * @param aRequest HttpServletRequest.
   * @param aCommand RoleCommand.
   * @param aErrors Errors.
   * @return ModelAndView.
   */
  @RequestMapping(params = "adminRequestedAction" + "=delete", method = RequestMethod.POST)
  public ModelAndView delete(HttpServletRequest aRequest,
                             @ModelAttribute(AdminGeneralConstants.ADMIN_COMMAND) RoleCommand aCommand,
                             Errors aErrors)
  {
    String errorMessage = mRoleService.deleteWebRole(aCommand.getRole().getPk());
    if (errorMessage != null)
    {
      aErrors.reject(errorMessage, new String[] {"Role"}, "Role");

      ModelAndView mav = new ModelAndView(getViewName());
      mav.addObject(AdminGeneralConstants.ADMIN_COMMAND, aCommand);
      return mav;
    }

    return getRedirectListView();
  }

  private ModelAndView getRedirectListView()
  {
    return new ModelAndView(new RedirectView(TabsAccessibilityInterceptor.ROLE_LIST_URL));
  }

  /**
   * Returns view name as a String.
   *
   * @return String
   */
  public String getViewName()
  {
    return "hs_roleEdit";
  }
}
